/**
 * 定时任务的处理入口
 * 
 * Created by wbx on 2022/5/1
 */
(() => {
  const ISchedulerFactory = Host.type('Quartz.ISchedulerFactory', 'Quartz');
  const JobBuilder = Host.type('Quartz.JobBuilder', 'Quartz');
  const TriggerBuilder = Host.type('Quartz.TriggerBuilder', 'Quartz');
  const CronScheduleBuilder = Host.type('Quartz.CronScheduleBuilder', 'Quartz');
  const TriggerKey = Host.type('Quartz.TriggerKey', 'Quartz');
  const WorkerInvokeJob = Host.type('MetaServer.WorkerInvokeJob', 'MetaServer');

  return function ({ Action, Record }) {
    switch (Action) {
      case "Start": {
        let { rows } = A.db.execute('KERNEL', "SELECT ID,CFSJ,ZYMC,ZYCS FROM DSRW WHERE JHBJ=1");
        if (rows.length === 0) return;
        const SchedulerFactory = App.Services.GetService(Host.typeOf(ISchedulerFactory));
        const task = SchedulerFactory.GetScheduler();
        task.Wait();
        const IScheduler = task.Result;
        rows.forEach(t => {
          const payload = JSON.stringify({ Name: 'Schedule', Param: { Action: 'Trigger', Record: { ID: t.ID, 作业名称: t.ZYMC, 作业参数: t.ZYCS } } });
          const job = JobBuilder.Create(Host.typeOf(WorkerInvokeJob)).WithIdentity(t.ID).UsingJobData("payload", payload).Build();
          const scheduleBuilder = CronScheduleBuilder.CronSchedule(t.CFSJ);
          const trigger = TriggerBuilder.Create().WithSchedule(scheduleBuilder).WithIdentity(t.ID).Build();
          IScheduler.ScheduleJob(job, trigger);
        });
        break;
      }
      case "Save": {
        if (Record.激活标记) {
          if (!Record.ID) Record.ID = A.guid();
          // 添加到调度器
          const SchedulerFactory = App.Services.GetService(Host.typeOf(ISchedulerFactory));
          const task = SchedulerFactory.GetScheduler();
          task.Wait();
          const IScheduler = task.Result;
          const triggerKey = Host.newObj(TriggerKey, Record.ID);
          const exists = IScheduler.CheckExists(triggerKey);
          exists.Wait();
          if (exists.Result) IScheduler.UnscheduleJob(triggerKey);
          const payload = JSON.stringify({ Name: 'Schedule', Param: { Action: 'Trigger', Record } });
          const job = JobBuilder.Create(Host.typeOf(WorkerInvokeJob)).WithIdentity(Record.ID).UsingJobData("payload", payload).Build();
          const scheduleBuilder = CronScheduleBuilder.CronSchedule(Record.触发时间);
          const trigger = TriggerBuilder.Create().WithSchedule(scheduleBuilder).WithIdentity(Record.ID).Build();
          const t = IScheduler.ScheduleJob(job, trigger);
          t.Wait();
          Logger.Info(`ScheduleJob: [${Record.ID}] ${Record.名称}`);
        } else {
          if (Record.ID) {
            // 从调度器中移除
            const SchedulerFactory = App.Services.GetService(Host.typeOf(ISchedulerFactory));
            const task = SchedulerFactory.GetScheduler();
            task.Wait();
            const IScheduler = task.Result;
            const triggerKey = Host.newObj(TriggerKey, Record.ID);
            const t = IScheduler.UnscheduleJob(triggerKey);
            t.Wait();
            Logger.Info(`UnscheduleJob: [${Record.ID}] ${Record.名称}`);
          }
        }
        // 保存任务记录
        A.card('定时任务').save(Record);
        break;
      }
      case "Remove": {
        if (!Record.ID) return;
        // 从调度器中移除
        const SchedulerFactory = App.Services.GetService(Host.typeOf(ISchedulerFactory));
        const task = SchedulerFactory.GetScheduler();
        task.Wait();
        const IScheduler = task.Result;
        const triggerKey = Host.newObj(TriggerKey, Record.ID);
        const t = IScheduler.UnscheduleJob(triggerKey);
        t.Wait();
        Logger.Info(`UnscheduleJob: [${Record.ID}] ${Record.名称}`);
        // 删除记录
        A.card('定时任务').delete(Record);
        break;
      }
      case "Trigger": {
        let args;
        try {
          args = Record.作业参数 ? JSON.parse(Record.作业参数) : undefined
        } catch { }
        // 更新任务执行时间
        Logger.Debug(`Job Triggered: [${Record.ID}] ${new Date().toLocaleString()}`);
        A.card('定时任务').save({ ID: Record.ID, 上次运行时间: new Date(), 上次运行结果: null });
        // 调用作业
        try {
          const job = A.job(Record.作业名称);
          const result = job(Record.ID, args);
          const result_str = (typeof (result) === 'string' ? result : JSON.stringify(result)) ?? '<EMPTY>';
          // 更新作业执行结果
          Logger.Debug(`Job Finished: [${Record.ID}] ${result_str}`);
          A.card('定时任务').save({ ID: Record.ID, 上次运行结果: result_str });
        } catch (e) {
          // 更新作业执行结果
          A.card('定时任务').save({ ID: Record.ID, 上次运行结果: e.message });
          Logger.Error(`Job Failed: [${Record.ID}] ${e.stack}`);
        }
      }
    }
  };
})();